package org.jiangy.authentication;

import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;

import static org.jiangy.Constants.DEFAULT_KEY_ID;

/**
 * TODO: JwtUtils 需要重写
 * <p>创建时间: 2024/8/12 </p>
 *
 * @author <a href="mailto:jiangliu0316@outlook.com" rel="nofollow">蒋勇</a>
 */
public enum JwtUtils {

    INSTANCE;

    private RsaJsonWebKey jwk;

    JwtUtils() {
        try {
            jwk = RsaJwkGenerator.generateJwk(2048);
            jwk.setKeyId(DEFAULT_KEY_ID);
        } catch (JoseException e) {
            System.out.println(e.getMessage());
        }
    }

    public String generateJwt(JwtClaims jwtClaims) throws JoseException {
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload(jwtClaims.toJson());
        // 在JWT/JWS上设置签名算法，以保护声明的完整性
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
        //set private key
        jws.setKey(jwk.getPrivateKey());
        return jws.getCompactSerialization();
    }

    public JwtClaims parseJwt(String jwt) throws InvalidJwtException {
        //解析idToken, 验签
        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                // JWT必须有一个过期时间
                .setRequireExpirationTime()
                //但过期时间不能太疯狂
                .setMaxFutureValidityInMinutes(300)
                // 在验证基于时间的声明时留出一些余地，以考虑时钟偏差
                .setAllowedClockSkewInSeconds(30)
                // JWT必须有主题声明
                .setRequireSubject()
                // JWT需要由谁签发
                .setExpectedIssuer("http://localhost:8080")
                // to whom the JWT is intended for
                .setExpectedAudience("shop")
                //用公钥验证签名
                .setVerificationKey(jwk.getKey())
                .build();

        return jwtConsumer.processToClaims(jwt);
    }

}
